﻿using System;
using System.IO;
using System.Threading;

namespace CabConfigProvisioning
{
    public class MemoryFile : IDisposable
    {
        private const string CACHE_PREFIX = "$$FILE_CACHE$$";

        private static int _nCounter;

        private MemoryCache _cache;

        private FileInfo _file;

        private string _sName;

        private volatile bool _bLoaded;

        private byte[] _content;

        public ushort Date { get; set; }

        public ushort Time { get; set; }

        public ushort Attributes { get; set; }

        public static bool IsCacheFile(string sFilePath)
        {
            return sFilePath.StartsWith(CACHE_PREFIX);
        }

        public MemoryFile(MemoryCache cache, FileInfo file, bool bKeepOriginalName)
        {
            _cache = cache;
            _file = file;
            _sName = bKeepOriginalName ? file.FullName : CACHE_PREFIX + Interlocked.Increment(ref _nCounter) + Path.GetExtension(file.FullName);
        }

        public MemoryFile(MemoryCache cache, FileInfo file, byte[] content)
        {
            _cache = cache;
            _sName = CACHE_PREFIX + Interlocked.Increment(ref _nCounter) + Path.GetExtension(file.FullName);
            _content = content;
            _bLoaded = true;
        }

        private byte[] Read()
        {
            lock (this)
            {
                if(_bLoaded)
                    return _content;
                Stream stream = new FileStream(_file.FullName, FileMode.Open, FileAccess.Read);
                byte[] buf = new byte[_file.Length];
                stream.Read(buf, 0, buf.Length);
                _content = buf;
                _bLoaded = true;
                return _content;
            }
        }

        public byte[] Content
        {
            get { return _bLoaded ? _content : Read(); }
        }

        public Stream Stream
        {
            get
            {
                return new MemoryStream(_bLoaded ? _content : Read());
            }
        }

        public string FullName
        {
            get { return _sName; }
        }

        public void Dispose()
        {
            _cache.Remove(_sName);
            _content = null;
        }
    }
}
